/*
 * @Author: 0x9DEFA478
 * @Date: 2021-12-20 17:33:18
 * @LastEditTime: 2021-12-20 21:39:55
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "H_TS_API.h"
#include "Peripheral.h"


//==============================================================================================================================
//
//       桥接接口
//
//==============================================================================================================================

#define vH_TS_CPULoad_T             400000


extern void *pvPortMalloc( size_t xWantedSize );
extern void vPortFree( void *pv );

extern int RTOS_IsIdleThread(void);

static void* volatile RTOS_IdleProcess_v;
static void (* volatile RTOS_IdleProcess)(void*);

static volatile int H_TS_CPU_Load=-1;
static volatile TickType_t H_TS_RunTickCnt=0;
static volatile TickType_t H_TS_IdleTickCnt=0;


static void RTOS_TickCallback(void* v){
  extern void xPortSysTickHandler();
  xPortSysTickHandler();
}

//FreeRTOS调用 启用Tick
void vPortSetupTimerInterrupt(){

  TimeTick_Set_IRQ_Callback(RTOS_TickCallback,NULL);
}

//RTOS 空闲调用
void vApplicationIdleHook(){
  void (*IdleProcess)(void *);

  IdleProcess=RTOS_IdleProcess;

  if(IdleProcess!=NULL){
    IdleProcess(RTOS_IdleProcess_v);
  }
}








TickType_t H_TS_GetDT(){
  static TickType_t lastT=0;
  TickType_t nowT;
  TickType_t r;

  nowT=(TickType_t)TIM5->CNT;

  r=nowT-lastT;
  lastT=nowT;

  return r;
}


void H_TS_GetCPULoadCall(){

  TickType_t dt;
  TickType_t RunTickCnt;
  TickType_t IdleTickCnt;

  dt=H_TS_GetDT();
  RunTickCnt=H_TS_RunTickCnt;
  IdleTickCnt=H_TS_IdleTickCnt;

  RunTickCnt+=dt;
  if(RTOS_IsIdleThread()!=0){
    IdleTickCnt+=dt;
  }
  if(RunTickCnt>vH_TS_CPULoad_T){
    H_TS_CPU_Load=1000-(1000*IdleTickCnt/RunTickCnt);
    H_TS_RunTickCnt=0;
    H_TS_IdleTickCnt=0;
  }else{
    H_TS_RunTickCnt=RunTickCnt;
    H_TS_IdleTickCnt=IdleTickCnt;
  }
}
















//==============================================================================================================================
//
//       普通方法
//
//==============================================================================================================================

/**
 * @brief 挂起线程调度 调度器挂起期间 不能使用任何H_TS的方法(防止这些方法恢复了任务调度)
 * @return 无
 */
void H_TS_SchedulerSuspend(void){

  vTaskSuspendAll();
}

/**
 * @brief 恢复任务调度  不能使用任何H_TS的方法(防止这些方法恢复了任务调度)
 * @param isCallPendSV 0:由调度器决定是否触发PendSV 其他:返回前触发PendSV
 * @return 无
 */
void H_TS_ResumeScheduler(int isCallPendSV){

  (void)xTaskResumeAll();
}

/**
 * @brief 获取CPU使用率
 * @return CPU使用率 单位0.1%
 */
int H_TS_GetCPULoad(void){
  return H_TS_CPU_Load;
}

/**
 * @brief 设置空闲函数空闲时调用的方法
 * @param IdleProcess 空闲回调
 * @return 无
 */
void H_TS_SetIdleProcess(void (*IdleProcess)(void*)){
  RTOS_IdleProcess=IdleProcess;
}

/**
 * @brief 获取堆栈内存占用
 * @return 堆栈内存占用率 单位0.1%
 */
int H_TS_GetStackUtilization(void){
  return -1;
}

/**
 * @brief 开始线程调度 使用此方法之前 必须调用H_TS_Init()
 * @return 正常情况 该方法不会返回
 */
void H_TS_StartScheduler(void){
  vTaskStartScheduler();
}




//==============================================================================================================================
//
//       线程相关方法
//
//==============================================================================================================================

//任务方法
static void TaskFunction(void* v){

  H_TS_Thread* _this;

  _this=v;

  _this->Code(_this->v);

  vTaskDelete(NULL);
}


/**
 * @brief 创建一个线程句柄 分配栈空间 (此方法并不会开始运行线程,需使用H_TS_ThreadStart()线程才会运行)
 * @param StackSize 堆栈大小(如果不是sizeof(void*)的倍数 会被增加到最近的sizeof(void*)倍数)
 * @param Feature 一些特性信息
 * @return 线程句柄 如果为NULL 代表失败
 */
//H_TS_Thread* new_H_TS_Thread(Hsize StackSize,Huint32 Feature){}

/**
 * @brief 释放一个线程占用的资源
 * @param Thread 要释放的线程
 * @return 0:成功 -1:失败 线程未完全停止
 */
//int delete_H_TS_Thread(H_TS_Thread* Thread){}

/**
 * @brief 开始运行一个线程 如果未开始线程调度 线程将在开始线程调度后运行
 * @param Thread 线程句柄 可以是已停止的线程句柄
 * @param Code 线程代码
 * @param v 线程传入参数
 * @param Priority 优先级
 * @return 0:成功 -1:Thread不为停止状态 -2:优先级无效
 */
//int H_TS_ThreadStart(H_TS_Thread* Thread,int (*Code)(void*),void* v,Hsize Priority){}

/**
 * @brief 开始运行一个线程 这个方法于H_TS_ThreadStart()不同的地方在于:
 *          它不需要传入优先级, 它会自动将线程优先级设置为当前所有线程的最高级还要高一级 即Priority为现有线程的最小值减1
 *          在存在空闲的高优先级的情况下(一般int有32位, 几乎不用考虑优先级用完的情况) 它不需要去避免优先级冲突的问题 这个方法很适合需要临时新建一个线程的情况
 * @param Thread 线程句柄 可以是已停止的线程句柄
 * @param Code 线程代码
 * @param v 线程传入参数
 * @return 0:成功 -1:Thread不为停止状态
 */
//int H_TS_ThreadStart_MaxPriority(H_TS_Thread* Thread,int (*Code)(void*),void* v);

/**
 * @brief 开始运行一个线程 这个方法于H_TS_ThreadStart()不同的地方在于:
 *          它不需要传入优先级, 它会自动将线程优先级设置为当前所有线程的最低级还要低一级 即Priority为现有线程的最小值加1
 *          (这个"当前所有线程"不包括空闲线程 以保证空闲线程优先级是最低的)
 * @param Thread 线程句柄 可以是已停止的线程句柄
 * @param Code 线程代码
 * @param v 线程传入参数
 * @return 0:成功 -1:Thread不为停止状态
 */
//int H_TS_ThreadStart_MinPriority(H_TS_Thread* Thread,int (*Code)(void*),void* v);

/**
 * @brief 开始运行一个线程 这个方法于H_TS_ThreadStart()不同的地方在于:
 *          它不需要传入优先级, 它会自动将线程优先级设置为等于高于接近refPriority且空闲的一个优先级
 * @param Thread 线程句柄 可以是已停止的线程句柄
 * @param Code 线程代码
 * @param v 线程传入参数
 * @param refPriority 参考优先级
 * @return 0:成功 -1:Thread不为停止状态
 */
//int H_TS_ThreadStart_HighPriority(H_TS_Thread* Thread,int (*Code)(void*),void* v,Hsize refPriority);

/**
 * @brief 开始运行一个线程 这个方法于H_TS_ThreadStart()不同的地方在于:
 *          它不需要传入优先级, 它会自动将线程优先级设置为等于低于接近refPriority且空闲的一个优先级 但不会比空闲线程低
 * @param Thread 线程句柄 可以是已停止的线程句柄
 * @param Code 线程代码
 * @param v 线程传入参数
 * @param refPriority 参考优先级
 * @return 0:成功 -1:Thread不为停止状态
 */
//int H_TS_ThreadStart_LowPriority(H_TS_Thread* Thread,int (*Code)(void*),void* v,Hsize refPriority);

/**
 * @brief 新建并开始一个新线程 如果未开始线程调度 线程将在开始线程调度后运行
 * @param Code 线程代码
 * @param v 线程传入参数
 * @param StackSize 堆栈大小(如果不是sizeof(void*)的倍数 会被增加到最近的sizeof(void*)倍数)
 * @param Priority 优先级
 * @param Feature 一些特性信息
 * @return 线程句柄 NULL:失败 其他:成功
 */
H_TS_Thread* H_TS_StartNewThread(int (*Code)(void*),void* v,Hsize StackSize,Hsize Priority,Huint32 Feature){
  H_TS_Thread* r;
  BaseType_t result;

  (void)Feature;

  r=pvPortMalloc(sizeof(H_TS_Thread));
  if(r==NULL){
    goto Error0;
  }

  r->Code=Code;
  r->v=v;

  if(Priority>=configMAX_PRIORITIES){
    Priority=configMAX_PRIORITIES-1;
  }

  if(Priority<1){
    Priority=1;
  }

  result=xTaskCreate(TaskFunction,"Task",StackSize/sizeof(StackType_t),r,Priority,&r->thread);

  if(result!=pdTRUE){
    goto Error1;
  }

  return r;
Error1:
  vPortFree(r);
Error0:
  return NULL;
}

/**
 * @brief 新建并开始一个新线程 如果未开始线程调度 线程将在开始线程调度后运行
 *        它不需要传入优先级, 它会自动将线程优先级设置为当前所有线程的最高级还要高一级 即Priority为现有线程的最小值减1
 *          在存在空闲的高优先级的情况下(一般int有32位, 几乎不用考虑优先级用完的情况) 它不需要去避免优先级冲突的问题 这个方法很适合需要临时新建一个线程的情况
 * @param Code 线程代码
 * @param v 线程传入参数
 * @param StackSize 堆栈大小(如果不是sizeof(void*)的倍数 会被增加到最近的sizeof(void*)倍数)
 * @param Feature 一些特性信息
 * @return 线程句柄 NULL:失败 其他:成功
 */
H_TS_Thread* H_TS_StartNewThread_MaxPriority(int (*Code)(void*),void* v,Hsize StackSize,Huint32 Feature){
  return H_TS_StartNewThread(Code,v,StackSize,configMAX_PRIORITIES-1,0);
}

/**
 * @brief 新建并开始一个新线程 如果未开始线程调度 线程将在开始线程调度后运行
 *          它不需要传入优先级, 它会自动将线程优先级设置为当前所有线程的最低级还要低一级 即Priority为现有线程的最小值加1
 *          (这个"当前所有线程"不包括空闲线程 以保证空闲线程优先级是最低的)
 * @param Code 线程代码
 * @param v 线程传入参数
 * @param StackSize 堆栈大小(如果不是sizeof(void*)的倍数 会被增加到最近的sizeof(void*)倍数)
 * @param Feature 一些特性信息
 * @return 线程句柄 NULL:失败 其他:成功
 */
H_TS_Thread* H_TS_StartNewThread_MinPriority(int (*Code)(void*),void* v,Hsize StackSize,Huint32 Feature){
  return H_TS_StartNewThread(Code,v,StackSize,1,0);
}

/**
 * @brief 新建并开始一个新线程 如果未开始线程调度 线程将在开始线程调度后运行
 *          它不需要传入优先级, 它会自动将线程优先级设置为等于高于接近refPriority且空闲的一个优先级
 * @param Code 线程代码
 * @param v 线程传入参数
 * @param StackSize 堆栈大小(如果不是sizeof(void*)的倍数 会被增加到最近的sizeof(void*)倍数)
 * @param refPriority 参考优先级
 * @param Feature 一些特性信息
 * @return 线程句柄 NULL:失败 其他:成功
 */
H_TS_Thread* H_TS_StartNewThread_HighPriority(int (*Code)(void*),void* v,Hsize StackSize,Hsize refPriority,Huint32 Feature){
  return H_TS_StartNewThread(Code,v,StackSize,refPriority,0);
}

/**
 * @brief 新建并开始一个新线程 如果未开始线程调度 线程将在开始线程调度后运行
 *          它不需要传入优先级, 它会自动将线程优先级设置为等于低于接近refPriority且空闲的一个优先级 但不会比空闲线程低
 * @param Code 线程代码
 * @param v 线程传入参数
 * @param StackSize 堆栈大小(如果不是sizeof(void*)的倍数 会被增加到最近的sizeof(void*)倍数)
 * @param refPriority 参考优先级
 * @param Feature 一些特性信息
 * @return 线程句柄 NULL:失败 其他:成功
 */
H_TS_Thread* H_TS_StartNewThread_LowPriority(int (*Code)(void*),void* v,Hsize StackSize,Hsize refPriority,Huint32 Feature){
  return H_TS_StartNewThread(Code,v,StackSize,refPriority,0);
}

/**
 * @brief 结束线程自身
 * @param RetVal 线程返回值
 * @return 无
 */
void H_TS_ThreadExit(int RetVal){

  vTaskDelete(NULL);
  (void)RetVal;
}

/**
 * @brief 由线程调用, 获取线程本身的句柄
 * @return 线程本身的句柄
 */
H_TS_Thread* H_TS_GetThisThread(void){
  static H_TS_Thread thread={
    .StackMaxUsage=0
  };

  return &thread;
}

/**
 * @brief 获取所有线程的信息
 * @return 线程信息链表, 如果为NULL则代表失败
 */
H_TS_ThreadInfo* H_TS_ThreadInfoGet(void){
  return NULL;
}

/**
 * @brief 释放线程信息链表
 * @param Info 线程信息
 * @return 无
 */
void H_TS_ThreadInfoFree(H_TS_ThreadInfo* Info){

}

/**
 * @brief 线程休眠
 * @param NumOfTick 休眠的tick数
 * @return 无
 */
void H_TS_ThreadSleep(H_TS_Tick NumOfTick){
  vTaskDelay(NumOfTick);
}

/**
 * @brief 初始化线程调度器
 * @param v 空闲线程传入参数
 * @param IdleThreadStackSize 空闲线程堆栈大小
 * @return 0:成功 其他:内存申请失败
 */
int H_TS_Init(void* v,Hsize IdleThreadStackSize){
  RTOS_IdleProcess_v=v;
  (void)IdleThreadStackSize;
  return 0;
}




//==============================================================================================================================
//
//       锁相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个锁
 * @return 锁对象 如果为NULL 则失败
 */
H_TS_Lock* new_H_TS_Lock(void){
  return xSemaphoreCreateRecursiveMutex();
}

/**
 * @brief 删除一个锁
 * @param Lock 要删除的锁对象
 * @return 0:成功 -1:锁正在被其他线程占用
 */
int delete_H_TS_Lock(H_TS_Lock* Lock){
  vSemaphoreDelete(Lock);
  return 0;
}

/**
 * @brief 锁定一个锁 如果锁正被别的线程占用,则等待直到锁被释放
 * @param Lock 要锁定的锁对象
 * @return 0:锁正常锁定 其他:锁已经被该线程锁定
 */
int H_TS_Locking(H_TS_Lock* Lock){
  BaseType_t result;

  result=xSemaphoreTakeRecursive(Lock,portMAX_DELAY);

  if(result!=pdTRUE){
    //printf("锁获取出错\r\n");
    for(;;){
    }
  }

  return 0;
}

/**
 * @brief 释放一个锁
 * @param Lock 要释放的锁
 * @return 无
 */
void H_TS_UnLock(H_TS_Lock* Lock){
  BaseType_t result;

  result=xSemaphoreGiveRecursive(Lock);

  if(result!=pdTRUE){
    //printf("锁释放出错\r\n");
    for(;;){
    }
  }
}




//==============================================================================================================================
//
//       二值信号量相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个二值信号量
 * @return 二值信号量对象 如果为NULL 则失败
 */
H_TS_BinarySemaphore* new_H_TS_BinarySemaphore(void){
  return xSemaphoreCreateBinary();
}

/**
 * @brief 删除二值信号量
 * @param BinarySemaphore 要删除的二值信号量对象
 * @return 0:成功 -1:有线程因此邮箱阻塞
 */
int delete_H_TS_BinarySemaphore(H_TS_BinarySemaphore* BinarySemaphore){
  vSemaphoreDelete(BinarySemaphore);
  return 0;
}

/**
 * @brief 释放一个二值信号量 由中断调用
 * @param BinarySemaphore 要操作的二值信号量
 * @return 0:成功 -1:队列已满
 */
int H_TS_BinarySemaphoreGive_ISR(H_TS_BinarySemaphore* BinarySemaphore){
  BaseType_t IsScheduler;
  BaseType_t result;

  result=xSemaphoreGiveFromISR(BinarySemaphore,&IsScheduler);

  if(result!=pdTRUE){
    return -1;
  }

  portYIELD_FROM_ISR(IsScheduler);
  return 0;
}

/**
 * @brief 释放一个二值信号量
 * @param BinarySemaphore 要操作的二值信号量
 * @return 0:成功 -1:队列已满
 */
int H_TS_BinarySemaphoreGive(H_TS_BinarySemaphore* BinarySemaphore){
  BaseType_t result;

  result=xSemaphoreGive(BinarySemaphore);

  if(result!=pdTRUE){
    return -1;
  }

  return 0;
}

/**
 * @brief 获取二值信号量
 * @param BinarySemaphore 要操作的二值信号量
 * @return 如果无信号量 将一直阻塞 直到获取成功
 */
void H_TS_BinarySemaphoreTake(H_TS_BinarySemaphore* BinarySemaphore){
  BaseType_t result;

  result=xSemaphoreTake(BinarySemaphore,portMAX_DELAY);

  if(result!=pdTRUE){
    //printf("信号量获取出错\r\n");
    for(;;){
    }
  }
}

/**
 * @brief 尝试获取二值信号量
 * @param BinarySemaphore 要操作的二值信号量
 * @return 0:成功 其他:获取失败
 */
int H_TS_BinarySemaphoreTryTake(H_TS_BinarySemaphore* BinarySemaphore){
  BaseType_t result;

  result=xSemaphoreTake(BinarySemaphore,0);

  if(result!=pdTRUE){
    return -1;
  }

  return 0;
}

/**
 * @brief 获取二值信号量 时间限制
 * @param BinarySemaphore 要操作的二值信号量
 * @param Timeout 最大等待时间
 * @return 0:成功 其他:获取失败
 */
int H_TS_BinarySemaphoreTake_Time(H_TS_BinarySemaphore* BinarySemaphore,H_TS_Tick Timeout){
  BaseType_t result;

  result=xSemaphoreTake(BinarySemaphore,Timeout);

  if(result!=pdTRUE){
    return -1;
  }

  return 0;
}




//==============================================================================================================================
//
//       信号量相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个信号量
 * @param MaxCount 最大信号量数量(如果为1 则相当于为二值信号量)
 * @return 信号量对象 如果为NULL 则失败
 */
H_TS_Semaphore* new_H_TS_Semaphore(Hsize MaxCount){
  return xSemaphoreCreateCounting(MaxCount,0);
}

/**
 * @brief 删除一个信号量
 * @param Semaphore 要删除的信号量对象
 * @return 0:成功 -1:有线程因此信号量阻塞
 */
int delete_H_TS_Semaphore(H_TS_Semaphore* Semaphore){
  vSemaphoreDelete(Semaphore);
  return 0;
}

/**
 * @brief 释放一个信号量 由中断调用
 * @param Semaphore 要操作的信号量
 * @return 0:成功 -1:队列已满
 */
int H_TS_SemaphoreGive_ISR(H_TS_Semaphore* Semaphore){
  BaseType_t IsScheduler;
  BaseType_t result;

  result=xSemaphoreGiveFromISR(Semaphore,&IsScheduler);

  if(result!=pdTRUE){
    return -1;
  }

  portYIELD_FROM_ISR(IsScheduler);
  return 0;
}

/**
 * @brief 释放一个信号量
 * @param Semaphore 要操作的信号量
 * @return 0:成功 -1:队列已满
 */
int H_TS_SemaphoreGive(H_TS_Semaphore* Semaphore){
  BaseType_t result;

  result=xSemaphoreGive(Semaphore);

  if(result!=pdTRUE){
    return -1;
  }

  return 0;
}

/**
 * @brief 获取信号量
 * @param Semaphore 要操作的信号量
 * @return 如果无信号量 将一直阻塞 直到获取成功
 */
void H_TS_SemaphoreTake(H_TS_Semaphore* Semaphore){
  BaseType_t result;

  result=xSemaphoreTake(Semaphore,portMAX_DELAY);

  if(result!=pdTRUE){
    //printf("信号量获取出错\r\n");
    for(;;){
    }
  }
}

/**
 * @brief 尝试获取信号量
 * @param Semaphore 要操作的信号量
 * @return 0:成功 其他:获取失败
 */
int H_TS_SemaphoreTryTake(H_TS_Semaphore* Semaphore){
  BaseType_t result;

  result=xSemaphoreTake(Semaphore,0);

  if(result!=pdTRUE){
    return -1;
  }

  return 0;
}

/**
 * @brief 获取信号量 时间限制
 * @param Semaphore 要操作的信号量
 * @param Timeout 最大等待时间
 * @return 0:成功 其他:获取失败
 */
int H_TS_SemaphoreTake_Time(H_TS_Semaphore* Semaphore,H_TS_Tick Timeout){
  BaseType_t result;

  result=xSemaphoreTake(Semaphore,Timeout);

  if(result!=pdTRUE){
    return -1;
  }

  return 0;
}




//==============================================================================================================================
//
//       消息队列相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个消息队列
 * @param NumOfMessage 队列容量大小 队列最大可容纳(NumOfMessage-1)个消息 (全部占用与队列空的偏移指示是一致的,所以队列设计成不能占满)
 * @return 消息队列对象 如果为NULL 则失败
 */
H_TS_MessageQueue* new_H_TS_MessageQueue(Hsize NumOfMessage){
  return xQueueCreate(NumOfMessage,sizeof(void*)*2);
}

/**
 * @brief 删除一个消息队列
 * @param MessageQueue 要删除的消息队列对象
 * @return 0:成功 -1:有线程因此消息队列阻塞
 */
int delete_H_TS_MessageQueue(H_TS_MessageQueue* MessageQueue){
  vQueueDelete(MessageQueue);
  return 0;
}

/**
 * @brief 向消息队列发送消息 由中断调用
 * @param MessageQueue 要操作的消息队列
 * @param v0 消息指针0
 * @param v1 消息指针1
 * @return 0:成功 -1:队列已满
 */
int H_TS_MessageQueueSend_ISR(H_TS_MessageQueue* MessageQueue,void* v0,void* v1){
  void* src[2];
  BaseType_t result;
  BaseType_t IsScheduler;

  src[0]=v0;
  src[1]=v1;
  
  result=xQueueSendToBackFromISR(MessageQueue,src,&IsScheduler);

  if(result!=pdTRUE){
    return -1;
  }

  portYIELD_FROM_ISR(IsScheduler);
  return 0;
}

/**
 * @brief 向消息队列发送消息
 * @param MessageQueue 要操作的消息队列
 * @param v0 消息指针0
 * @param v1 消息指针1
 * @return 0:成功 -1:队列已满
 */
int H_TS_MessageQueueSend(H_TS_MessageQueue* MessageQueue,void* v0,void* v1){
  void* src[2];
  BaseType_t result;

  src[0]=v0;
  src[1]=v1;

  result=xQueueSendToBack(MessageQueue,src,portMAX_DELAY);

  if(result==pdTRUE){
    return 0;
  }

  return -1;
}

/**
 * @brief 从队列中读取消息
 * @param MessageQueue 要操作的队列
 * @param v0 存放消息空间的指针0
 * @param v1 存放消息空间的指针1
 * @return 如果无消息 将一直阻塞 直到获取成功
 */
void H_TS_MessageQueueReceive(H_TS_MessageQueue* MessageQueue,void** v0,void** v1){
  void* dst[2];
  BaseType_t result;

  result=xQueueReceive(MessageQueue,dst,portMAX_DELAY);

  if(result!=pdTRUE){
    //printf("消息队列接收出错\r\n");
    for(;;){
    }
  }

  v0[0]=dst[0];
  v1[0]=dst[1];
}

/**
 * @brief 尝试从队列中读取消息
 * @param MessageQueue 要操作的队列
 * @param v0 存放消息空间的指针0
 * @param v1 存放消息空间的指针1
 * @return 0:成功 其他:获取失败
 */
int H_TS_MessageQueueTryReceive(H_TS_MessageQueue* MessageQueue,void** v0,void** v1){
  void* dst[2];
  BaseType_t result;

  result=xQueueReceive(MessageQueue,dst,0);
  
  if(result!=pdTRUE){
    return -1;
  }

  v0[0]=dst[0];
  v1[0]=dst[1];

  return 0;
}

/**
 * @brief 从队列中读取消息 时间限制
 * @param MessageQueue 要操作的队列
 * @param v0 存放消息空间的指针0
 * @param v1 存放消息空间的指针1
 * @param Timeout 最大等待时间
 * @return 0:成功 其他:获取失败
 */
int H_TS_MessageQueueReceive_Time(H_TS_MessageQueue* MessageQueue,void** v0,void** v1,H_TS_Tick Timeout){
  void* dst[2];
  BaseType_t result;

  result=xQueueReceive(MessageQueue,dst,Timeout);
  
  if(result!=pdTRUE){
    return -1;
  }

  v0[0]=dst[0];
  v1[0]=dst[1];

  return 0;
}




//==============================================================================================================================
//
//       邮箱相关方法
//
//==============================================================================================================================

/**
 * @brief 新建一个邮箱
 * @param MaxNumOfMail 每一个内部邮箱的最大容纳个数+1 (最大容纳数=MaxNumOfMail-1)
 * @param MailSize 每个信息大小 单位:字节
 * @param NumOfMailboxs 内部邮箱个数
 * @return 邮箱对象 如果为NULL 则失败
 */
H_TS_Mailbox* new_H_TS_Mailbox(Hsize MaxNumOfMail,Hsize MailSize,Hsize NumOfMailboxs){
  (void)NumOfMailboxs;//对于FreeRTOS NumOfMailboxs是无意义的
  return xQueueCreate(MaxNumOfMail,MailSize);
}

/**
 * @brief 删除一个邮箱
 * @param Mailbox 要删除的邮箱对象
 * @return 0:成功 -1:有线程因此邮箱阻塞
 */
int delete_H_TS_Mailbox(H_TS_Mailbox* Mailbox){
  vQueueDelete(Mailbox);
  return 0;
}

/**
 * @brief 向邮箱发送数据 中断调用
 * @param Mailbox 要操作的邮箱
 * @param Data 指向要发送的数据
 * @return 0:成功 -1:邮箱已满
 */
int H_TS_MailboxPost_ISR(H_TS_Mailbox* Mailbox,void* Data){
  BaseType_t result;
  BaseType_t IsScheduler;
  
  result=xQueueSendToBackFromISR(Mailbox,Data,&IsScheduler);

  if(result!=pdTRUE){
    return -1;
  }

  portYIELD_FROM_ISR(IsScheduler);
  return 0;
}

/**
 * @brief 向邮箱发送数据
 * @param Mailbox 要操作的邮箱
 * @param Data 指向要发送的数据
 * @return 0:成功 -1:邮箱已满
 */
int H_TS_MailboxPost(H_TS_Mailbox* Mailbox,void* Data){
  BaseType_t result;

  result=xQueueSendToBack(Mailbox,Data,portMAX_DELAY);

  if(result==pdTRUE){
    return 0;
  }

  return -1;
}

/**
 * @brief 从邮箱中接收数据
 * @param Mailbox 要操作的邮箱
 * @param Data 指向容纳数据的内存
 * @return 无
 */
void H_TS_MailboxReceive(H_TS_Mailbox* Mailbox,void* Data){
  BaseType_t result;

  result=xQueueReceive(Mailbox,Data,portMAX_DELAY);

  if(result!=pdTRUE){
    //printf("消息队列接收出错\r\n");
    for(;;){
    }
  }
}

/**
 * @brief 尝试从邮箱中接收数据
 * @param Mailbox 要操作的邮箱
 * @param Data 指向容纳数据的内存
 * @return 0:成功 其他:获取失败
 */
int H_TS_MailboxTryReceive(H_TS_Mailbox* Mailbox,void* Data){
  BaseType_t result;

  result=xQueueReceive(Mailbox,Data,0);
  
  if(result!=pdTRUE){
    return -1;
  }

  return 0;
}

/**
 * @brief 从邮箱中接收数据 时间限制
 * @param Mailbox 要操作的邮箱
 * @param Data 指向容纳数据的内存
 * @param Timeout 最大等待时间
 * @return 0:成功 其他:获取失败
 */
int H_TS_MailboxReceive_Time(H_TS_Mailbox* Mailbox,void* Data,H_TS_Tick Timeout){
  BaseType_t result;

  result=xQueueReceive(Mailbox,Data,Timeout);
  
  if(result!=pdTRUE){
    return -1;
  }

  return 0;
}















